package info.yangguo.util;

import info.yangguo.pojo.Message00Pojo;
import info.yangguo.pojo.Message01Pojo;
import info.yangguo.pojo.Message10Pojo;
import info.yangguo.pojo.Message11Pojo;
import info.yangguo.pojo.RequestAttribute;
import info.yangguo.pojo.ResponseType;
import info.yangguo.pojo.SMS3Pojo;

import java.lang.reflect.Field;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author:杨果
 * @date:16/10/2 下午12:26
 *
 * Description:
 *
 */
public class Transfer {
    /**
     * 添加标识符
     */
    public static String encodeIdentifier(String value) {
        return "7E" + value + "7E";
    }

    /**
     * 删除标识符
     */
    public static String decodeIdentifier(String value) {
        Pattern pattern = Pattern.compile("^7E(.*)7E$");
        Matcher matcher = pattern.matcher(value);
        if (matcher.find()) {
            return matcher.group(1);
        } else {
            throw new RuntimeException("输入的字符串格式不正确");
        }
    }

    /**
     * 字符转义
     */
    public static String encodeTransferred(String value) {
        value = value.replaceAll("7D", "7D01");
        return value.replaceAll("7E", "7D02");
    }

    /**
     * 字符反转义
     */
    public static String decodeTransferred(String value) {
        value = value.replaceAll("7D02", "7E");
        return value.replaceAll("7D01", "7D");
    }

    /**
     * 添加长度位
     */
    public static String encodeLength(String value) {
        String lengthStr = Integer.toHexString(value.length() + 6).toUpperCase();
        lengthStr = hexGap(4, lengthStr);
        return lengthStr + value;
    }

    /**
     * 删除长度位
     */
    public static String decodeLength(String value) {
        String lengthStr = value.substring(0, 4);
        int length = Integer.valueOf(lengthStr, 16);
        if (value.length() != length * 2) {
            throw new RuntimeException("传入的数据不合法");
        }
        return value;
    }

    /**
     * 编码MEID
     */
    public static String encodeMEID(String MEID, String value) {
        StringBuilder meidBuilder = new StringBuilder().append(MEID);
        for (int i = 0; i < 16 - MEID.length(); i++) {
            meidBuilder.append("F");
        }
        meidBuilder.append(value);
        return meidBuilder.toString();
    }

    /**
     * 解码MEID
     * <p>
     * 数组第一位表示MEID, 数组第二位表示去掉MEID之后的字符串.
     */
    public static String[] decodeMEID(String value) {
        String meid = value.substring(0, 16);
        Pattern pattern = Pattern.compile("(.*)F$");
        for (int i = 0; i < 16; i++) {
            Matcher matcher = pattern.matcher(meid);
            if (matcher.find()) {
                meid = matcher.group(1);
            } else {
                break;
            }
        }
        value = value.substring(16);
        String[] result = new String[2];
        result[0] = meid;
        result[1] = value;
        return result;
    }

    /**
     * 编码手机号码
     */
    public static String encodePhoneNo(String phoneNo, String value) {
        StringBuilder phoneNoBuilder = new StringBuilder().append(phoneNo);
        for (int i = 0; i < 16 - phoneNo.length(); i++) {
            phoneNoBuilder.append("F");
        }
        phoneNoBuilder.append(value);
        return phoneNoBuilder.toString();
    }

    /**
     * 解码手机号码
     * <p>
     * 数组第一位表示手机号码,第二位表示去掉手机号的字符串.
     */
    public static String[] decodePhoneNo(String value) {
        String phoneNo = value.substring(0, 16);
        Pattern pattern = Pattern.compile("(.*)F$");
        for (int i = 0; i < 16; i++) {
            Matcher matcher = pattern.matcher(phoneNo);
            if (matcher.find()) {
                phoneNo = matcher.group(1);
            } else {
                break;
            }
        }
        value = value.substring(16);
        String[] result = new String[2];
        result[0] = phoneNo;
        result[1] = value;
        return result;
    }

    /**
     * 编码消息序列号
     */
    public static String encodeSerialNo(int serialNo, String value) {
        if (serialNo > 255) {
            throw new RuntimeException("序列号不合法");
        } else {
            String serialNoHexStr = Integer.toHexString(serialNo);
            if (serialNoHexStr.length() == 1) {
                serialNoHexStr = "0" + serialNoHexStr;
            }
            return serialNoHexStr + value;
        }
    }

    /**
     * 解码消息序列号
     * <p>
     * 数组第一位表示序列号,数组第二位表示去掉序列号之后的字符串.
     */
    public static String[] decodeSerialNo(String value) {
        String[] result = new String[2];
        String serialNoStr = value.substring(0, 2);
        result[0] = String.valueOf(Integer.valueOf(serialNoStr, 16));
        result[1] = value.substring(2);
        return result;
    }

    /**
     * 编码消息属性
     */
    public static String encodeRequestAttribute(RequestAttribute requestAttribute, String value) {
        RequestAttribute.RequestType requestType = requestAttribute.getRequestType();
        RequestAttribute.RequestGrade requestGrade = requestAttribute.getRequestGrade();
        return Integer.toHexString(Integer.valueOf(requestType.getValue(), 2)) + requestGrade.getValue() + value;
    }

    /**
     * 解码消息属性
     * <p>
     * 数组第一位为RequestAttributes,数字第二位为剩余字符串.
     */
    public static Object[] decodeRequestAttribute(String value) {
        Object[] result = new Object[2];
        String attribute = value.substring(0, 2);
        String binaryStr = hexGap(8, Integer.toBinaryString(Integer.valueOf(attribute, 16)));
        String availableBinaryStr = binaryStr.substring(2, 8);
        String requestTypeStr = availableBinaryStr.substring(0, 2);
        String requestGradeStr = Integer.toHexString(Integer.valueOf(availableBinaryStr.substring(2, 6), 2));

        RequestAttribute requestAttribute = new RequestAttribute();
        for (RequestAttribute.RequestType type : RequestAttribute.RequestType.values()) {
            if (type.getValue().equals(requestTypeStr)) {
                requestAttribute.setRequestType(type);
            }
        }
        for (RequestAttribute.RequestGrade grade : RequestAttribute.RequestGrade.values()) {
            if (grade.getValue().equals(requestGradeStr.toUpperCase())) {
                requestAttribute.setRequestGrade(grade);
            }
        }

        result[0] = requestAttribute;
        result[1] = value.substring(2, value.length());
        return result;
    }

    /**
     * 编码00消息体
     */
    public static String encodeMessage00(Message00Pojo message00Pojo) {
        Field[] fields = message00Pojo.getClass().getFields();
        StringBuilder message = new StringBuilder();
        for (int i = 0; i < fields.length; i++) {
            String fieldName = fields[i].getName();
            try {
                String pValue = (String) fields[i].get(message00Pojo);
                if (pValue != null) {
                    if (i > 1) {
                        message.append(";");
                    }
                    message.append(fieldName.substring(fieldName.length() - 1));
                    message.append(pValue);
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        StringBuilder result = new StringBuilder();
        result.append("00");
        byte[] bytes = message.toString().getBytes();
        result.append(HexUtil.encodeHexStr(bytes));
        return result.toString();
    }

    /**
     * 解码00消息体
     */
    public static Message00Pojo decodeMessage00(String value) {
        Message00Pojo message00Pojo = new Message00Pojo();
        Field[] fields = Message00Pojo.class.getFields();

        String targetValue = value.substring(2);
        String message = new String(HexUtil.decodeHex(targetValue.toCharArray()));
        String[] messageBlocks = message.split(";");
        for (String messageBlock : messageBlocks) {
            String p = messageBlock.substring(0, 1);
            for (Field field : fields) {
                if (field.getName().endsWith(p)) {
                    try {
                        field.set(message00Pojo, messageBlock.substring(1));
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                    break;
                }
            }
        }
        return message00Pojo;
    }

    /**
     * 编码01消息体
     */
    public static String encodeMessage01(Message01Pojo message01Pojo) {
        Field[] fields = message01Pojo.getClass().getFields();
        StringBuilder message = new StringBuilder();
        for (int i = 0; i < fields.length; i++) {
            String fieldName = fields[i].getName();
            Class fieldClass = fields[i].getType();
            try {
                if (fieldClass.isAssignableFrom(Boolean.class)) {
                    Boolean pValue = (Boolean) fields[i].get(message01Pojo);
                    if (pValue != null && pValue == true) {
                        if (i > 1) {
                            message.append(";");
                        }
                        message.append(fieldName.substring(fieldName.length() - 1));
                    }
                } else if (fieldClass.isAssignableFrom(String.class)) {
                    String pValue = (String) fields[i].get(message01Pojo);
                    if (pValue != null) {
                        if (i > 1) {
                            message.append(";");
                        }
                        message.append(fieldName.substring(fieldName.length() - 1));
                        message.append(pValue);
                    }
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        StringBuilder result = new StringBuilder();
        result.append("01");
        result.append(HexUtil.encodeHexStr(message.toString().getBytes()));
        return result.toString();
    }

    /**
     * 解码01消息体
     */
    public static Message01Pojo decodeMessage01(String value) {
        Message01Pojo message01Pojo = new Message01Pojo();
        Field[] fields = Message01Pojo.class.getFields();

        String targetValue = value.substring(2);

        String message = new String(HexUtil.decodeHex(targetValue.toCharArray()));
        String[] messageBlocks = message.split(";");
        for (String messageBlock : messageBlocks) {
            String p = messageBlock.substring(0, 1);
            for (Field field : fields) {
                if (field.getName().endsWith(p)) {
                    Class fieldClass = field.getType();
                    if (fieldClass == Boolean.class) {
                        try {
                            field.set(message01Pojo, true);
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        }
                    }
                    if (fieldClass == String.class) {
                        try {
                            field.set(message01Pojo, messageBlock.substring(1));
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        }
                    }
                    break;
                }
            }
        }
        return message01Pojo;
    }

    /**
     * 编码10消息体
     */
    public static String encodeMessage10(Message10Pojo message10Pojo) {
        Field[] fields = message10Pojo.getClass().getFields();
        StringBuilder message = new StringBuilder();
        for (int i = 0; i < fields.length; i++) {
            String fieldName = fields[i].getName();
            try {
                String pValue = (String) fields[i].get(message10Pojo);
                if (pValue != null) {
                    if (i > 1) {
                        message.append(";");
                    }
                    message.append(fieldName.substring(fieldName.length() - 1));
                    message.append(pValue);
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        StringBuilder result = new StringBuilder();
        result.append("10");
        result.append(HexUtil.encodeHexStr(message.toString().getBytes()));
        return result.toString();
    }

    /**
     * 解码10消息体
     */
    public static Message10Pojo decodeMessage10(String value) {
        Message10Pojo message10Pojo = new Message10Pojo();
        Field[] fields = Message10Pojo.class.getFields();

        String targetValue = value.substring(2);

        String message = new String(HexUtil.decodeHex(targetValue.toCharArray()));
        String[] messageBlocks = message.split(";");
        for (String messageBlock : messageBlocks) {
            String p = messageBlock.substring(0, 1);
            for (Field field : fields) {
                if (field.getName().endsWith(p)) {
                    try {
                        field.set(message10Pojo, messageBlock.substring(1));
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                    break;
                }
            }
        }
        return message10Pojo;
    }

    /**
     * 编码11消息体
     */
    public static String encodeMessage11(Message11Pojo message11Pojo) {
        Pattern datePattern = Pattern.compile("\\d{2}");
        Pattern timePattern = Pattern.compile("\\d{6}");

        StringBuilder hexStr = new StringBuilder();
        hexStr.append("11");
        if (datePattern.matcher(message11Pojo.getDate()).matches()) {
            hexStr.append(message11Pojo.getDate());
        } else {
            throw new RuntimeException("日期格式错误");
        }
        //时间
        if (timePattern.matcher(message11Pojo.getTime()).matches()) {
            hexStr.append(message11Pojo.getTime());
        } else {
            throw new RuntimeException("时间格式错误");
        }
        //健康信息
        String stepNoStr = Integer.toHexString(message11Pojo.getStepNo());

        hexStr.append(hexGap(6, stepNoStr));
        hexStr.append("00");
        //状态
        StringBuilder status = new StringBuilder();
        status.append(message11Pojo.getStatus().S7 == true ? 1 : 0);
        status.append(message11Pojo.getStatus().S6 == true ? 1 : 0);
        status.append(message11Pojo.getStatus().S5 == true ? 1 : 0);
        if (message11Pojo.getStatus().S5) {
            status.append(message11Pojo.getStatus().S4);
        } else {
            status.append("0");
        }

        status.append(message11Pojo.getStatus().S3 == true ? 1 : 0);
        status.append(message11Pojo.getStatus().S2 == true ? 1 : 0);
        status.append(message11Pojo.getStatus().S1 == true ? 1 : 0);
        status.append(message11Pojo.getStatus().S0 == true ? 1 : 0);
        hexStr.append(hexGap(2, Integer.toHexString(Integer.valueOf(status.toString(), 2))));
        //告警
        StringBuilder warning = new StringBuilder();
        warning.append(message11Pojo.getWarning().W6 == true ? 1 : 0);
        warning.append(message11Pojo.getWarning().W5 == true ? 1 : 0);
        warning.append(message11Pojo.getWarning().W4 == true ? 1 : 0);
        warning.append(message11Pojo.getWarning().W3 == true ? 1 : 0);
        warning.append(message11Pojo.getWarning().W2 == true ? 1 : 0);
        warning.append(message11Pojo.getWarning().W1);
        warning.append(message11Pojo.getWarning().W0 == true ? 1 : 0);
        hexStr.append(hexGap(2, Integer.toHexString(Integer.valueOf(warning.toString(), 2))));
        //电量
        hexStr.append(hexGap(2, Integer.toHexString(message11Pojo.getPower())));
        //CDMA信号
        hexStr.append(hexGap(2, Integer.toHexString(Math.abs(message11Pojo.getCdma()))));
        return hexStr.toString();
    }

    /**
     * 解码11消息体
     */
    public static Message11Pojo decodeMessage11(String value) {
        Message11Pojo message11Pojo = new Message11Pojo();

        String targetValue = value.substring(2);
        String date = targetValue.substring(0, 2);
        String time = targetValue.substring(2, 8);
        String stepNo = targetValue.substring(8, 14);
        String status = targetValue.substring(16, 18);
        String waring = targetValue.substring(18, 20);
        String power = targetValue.substring(20, 22);
        String cdma = targetValue.substring(22, 24);
        String speed = targetValue.substring(24, 26);
        String direction = targetValue.substring(26, 28);
        String latitude = targetValue.substring(28, 36);
        String longitude = targetValue.substring(36, 44);
        String locationTypeAndSatelliteNo = targetValue.substring(44, 46);
        //WIFI暂时不解析
        Message11Pojo.WIFIInfo wifiInfo = new Message11Pojo.WIFIInfo();
        String wifi = targetValue.substring(46, 116);
        wifiInfo.setWifi1(wifi.substring(0, 14));
        wifiInfo.setWifi2(wifi.substring(14, 28));
        wifiInfo.setWifi3(wifi.substring(28, 42));
        wifiInfo.setWifi4(wifi.substring(42, 56));
        wifiInfo.setMAC(wifi.substring(56, 68));
        wifiInfo.setRSSI(Integer.valueOf(wifi.substring(68, 70), 16));

        //基站信息
        String baseStation = targetValue.substring(116, 224);

        message11Pojo.setDate(date);
        message11Pojo.setTime(time);
        message11Pojo.setStepNo(Integer.valueOf(stepNo, 16));
        message11Pojo.setPower(Integer.valueOf(power, 16));
        message11Pojo.setCdma(Integer.valueOf(cdma, 16));
        message11Pojo.setSpeed(Integer.valueOf(speed, 10));
        message11Pojo.setDirection(direction);
        message11Pojo.setLatitude(latitude);
        message11Pojo.setLongitude(longitude);
        String locationTypeAndSatelliteNoStr = Transfer.hexGap(8, Integer.toBinaryString(Integer.valueOf(locationTypeAndSatelliteNo, 16)));
        message11Pojo.setLocationType(locationTypeAndSatelliteNoStr.substring(0, 2));
        message11Pojo.setSatelliteNo(Integer.valueOf(locationTypeAndSatelliteNoStr.substring(2), 2));
        Message11Pojo.BaseStationInfo[] baseStationInfos = new Message11Pojo.BaseStationInfo[9];
        for (int i = 0; i < 6; i++) {
            Message11Pojo.BaseStationInfo baseStationInfo = new Message11Pojo.BaseStationInfo();
            String tmp = baseStation.substring(i * 18, (i + 1) * 18);
            baseStationInfo.setCELLID(Integer.valueOf(tmp.substring(0, 4), 16));
            baseStationInfo.setLAC(Integer.valueOf(tmp.substring(4, 8), 16));
            baseStationInfo.setMNC(tmp.substring(8, 12));
            baseStationInfo.setMCC(tmp.substring(12, 16));
            baseStationInfo.setSignal(Integer.valueOf(tmp.substring(16, 18), 16));
            baseStationInfos[i] = baseStationInfo;
        }
        message11Pojo.setBaseStationInfos(baseStationInfos);


        Message11Pojo.Status status1 = new Message11Pojo.Status();
        String statusStr = hexGap(8, Integer.toBinaryString(Integer.valueOf(status, 16)));
        if (statusStr.substring(0, 1).equals("1")) {
            status1.setS7(true);
        }
        if (statusStr.substring(1, 2).equals("1")) {
            status1.setS6(true);
        }
        if (statusStr.substring(2, 3).equals("1")) {
            status1.setS5(true);
        }
        status1.setS4(statusStr.substring(3, 4));
        if (statusStr.substring(4, 5).equals("1")) {
            status1.setS3(true);
        }
        if (statusStr.substring(5, 6).equals("1")) {
            status1.setS2(true);
        }
        if (statusStr.substring(6, 7).equals("1")) {
            status1.setS1(true);
        }
        if (statusStr.substring(7, 8).equals("1")) {
            status1.setS0(true);
        }
        message11Pojo.setStatus(status1);
        Message11Pojo.Warning warning1 = new Message11Pojo.Warning();
        String warningStr = hexGap(8, Integer.toBinaryString(Integer.valueOf(waring, 16)));
        warning1.setW6(false);
        if (warningStr.substring(1, 2).equals("1")) {
            warning1.setW5(true);
        }
        if (warningStr.substring(2, 3).equals("1")) {
            warning1.setW4(true);
        }
        if (warningStr.substring(3, 4).equals("1")) {
            warning1.setW3(true);
        }
        if (warningStr.substring(4, 5).equals("1")) {
            warning1.setW2(true);
        }
        warning1.setW1(warningStr.substring(5, 7));
        if (warningStr.substring(7, 8).equals("1")) {
            warning1.setW0(true);
        }

        message11Pojo.setWarning(warning1);

        return message11Pojo;
    }

    /**
     * 添加校验位
     */
    public static String encodeVerify(String value) {
        byte[] bytes = HexUtil.decodeHex(value.toCharArray());
        int sum = 0;
        for (int i = 0; i < bytes.length; i++) {
            sum += bytes[i];
        }

        String sumHex = Integer.toHexString(sum);
        return value + sumHex.substring(sumHex.length() - 2, sumHex.length()).toUpperCase();
    }

    /**
     * 校验数据并删除校验位
     */
    public static String decodeVerify(String value) {
        String sum1;
        if (value.length() % 2 == 0) {
            sum1 = value.substring(value.length() - 2, value.length());
            value = value.substring(0, value.length() - 2);
        } else {
            throw new RuntimeException("需要校验的数据应该为偶数位");
        }
        byte[] bytes = HexUtil.decodeHex(value.toCharArray());
        int sum2 = 0;
        for (int i = 0; i < bytes.length; i++) {
            sum2 += bytes[i];
        }
        String sum3 = Integer.toHexString(sum2);
        String sum4;
        if (sum3.length() >= 2) {
            sum4 = sum3.substring(sum3.length() - 2, sum3.length());
        } else {
            sum4 = hexGap(2, sum3);
        }
        if (sum1.equals(sum4.toUpperCase())) {
            return value.substring(4);
        } else {
            throw new RuntimeException("数据不合法");
        }
    }


    public static String encodeResponseType(ResponseType responseType) {
        return responseType.name();
    }

    public static ResponseType decodeResponseType(String value) {
        ResponseType result = null;
        for (ResponseType responseType : ResponseType.values()) {
            if (responseType.name().equals(value)) {
                result = responseType;
            }
        }
        return result;
    }

    private static String hexGap(int length, String target) {
        if (length < target.length()) {
            throw new RuntimeException("字符串的长度大于最大长度");
        }
        if (length % 2 != 0) {
            throw new RuntimeException("length必须要为偶数");
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length - target.length(); i++) {
            sb.append('0');
        }
        sb.append(target);
        return sb.toString();
    }

    public static String encodeSMS3(SMS3Pojo sms3Pojo) {
        StringBuilder message = new StringBuilder();
        message.append("3");
        message.append(sms3Pojo.getTargetAddress());
        String tmp = encodeSerialNo(sms3Pojo.getSerialNo(), message.toString());
        tmp = encodePhoneNo(sms3Pojo.getPhoneNo(), tmp);
        return "#ZTJ" + tmp;
    }
}
